package uuid;

import cn.hutool.core.util.ByteUtil;
import cn.hutool.core.util.NumberUtil;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;

import java.util.Calendar;

/**
 * @Author zhangtao
 * @create 2023/3/9 11:16
 */
@Slf4j
public class SnowFlakeUtil {
    public static final long EPOCH;

    public static void main(String[] args) {
        SnowFlakeUtil util = new SnowFlakeUtil();
        util.parseShardingSphere(840661057437339649L);
    }

    public void parseMybatisPlus(Long id) {
        String idStr = Long.toBinaryString(id);
        log.info("id:{}", id);
        log.info("dataCenterID:{}", NumberUtil.binaryToInt(idStr.substring(idStr.length() - 22, idStr.length() - 17)));
        log.info("workerID:{}", NumberUtil.binaryToInt(idStr.substring(idStr.length() - 17, idStr.length() - 12)));
        log.info("sequence:{}", NumberUtil.binaryToInt(idStr.substring(idStr.length() - 12)));
    }

    public long getMybatisPlusWorkerId(long datacenterId, String processId) {
        long maxWorkerId = -1L ^ (-1L << 5);
        StringBuilder mpid = new StringBuilder();
        mpid.append(datacenterId);
        mpid.append(processId);
        /*
         * MAC + PID 的 hashcode 获取16个低位
         */
        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
    }

    static {
        Calendar calendar = Calendar.getInstance();
        calendar.set(2016, Calendar.NOVEMBER, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        EPOCH = calendar.getTimeInMillis();
    }

    public void parseShardingSphere(Long id) {
        ByteUtil.longToBytes(id);
        String idStr = Long.toBinaryString(id);
        log.info("id:{}", id);
        log.info("date:{}", new DateTime(EPOCH + NumberUtil.binaryToLong(idStr.substring(0, idStr.length() - 22))).toString("YYYY-MM-dd HH:mm:ss"));
        log.info("timestamp:{}", EPOCH + NumberUtil.binaryToLong(idStr.substring(0, idStr.length() - 22)));
        log.info("workerID:{}", NumberUtil.binaryToInt(idStr.substring(idStr.length() - 22, idStr.length() - 12)));
        log.info("sequence:{}", NumberUtil.binaryToInt(idStr.substring(idStr.length() - 12)));
    }
}
